package game.cube;

import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLES20;
import android.opengl.Matrix;

public class Shader {
	private final String mVertexShader =
					"uniform mat4 uModelViewMatrix;\n" +
					"uniform mat4 uViewMatrix;\n" +
					"uniform mat4 uProjectionMatrix;\n" +
					"attribute vec4 aPosition;\n" +
					"attribute vec4 aColor;\n" +
					"varying vec4 fragColor;\n" +
					"void main() {\n" +
					"  gl_Position = uProjectionMatrix * uViewMatrix * uModelViewMatrix * aPosition;\n" +
					"  fragColor = aColor;\n" +
					"  gl_PointSize = 10.0;\n" +
					"}\n";

	private final String mFragmentShader =
					"precision mediump float;\n" +
					"varying vec4 fragColor;\n" +
					"void main() {\n" +
					"  gl_FragColor = fragColor;\n" +
					"  gl_FragColor.a = 0.2;" +
					"}\n";

	private int						mProgram;

	private int		 muModelViewMatrixHandle;
	private int			  muViewMatrixHandle;
	private int		muProjectionMatrixHandle;
	private int				maPositionHandle;
	private int				   maColorHandle;

	private float[]				 mProjMatrix	= new float[16];
	private float[]			mModelViewMatrix	= new float[16];
	private float[]				 mViewMatrix	= new float[16];

	private float[]						mEye	= new float[3];
	private float					  mAngle	= 0.0f;


	public Shader() {
	    mEye[0] = 5.0f * (float)Math.cos(3.14f / 180.0f * mAngle * 0.3f);
	    mEye[1] = 5.0f * (float)Math.sin(3.14f / 180.0f * mAngle);
	    mEye[2] = 5.0f * (float)Math.cos(3.14f / 180.0f * mAngle);
	}

	public void setViewPort(int width, int height) {
		GLES20.glViewport(0, 0, width, height);
		float ratio = (float) width / height;
		Matrix.frustumM(mProjMatrix, 0, -ratio * 0.3f, ratio * 0.3f, -1 * 0.3f, 1 * 0.3f , 1.0f, 100.0f);
	}

	public void initialize() {
		mProgram = createProgram(mVertexShader, mFragmentShader);
		if (mProgram <= 0) {
			return;
		}
		        maPositionHandle = GLES20.glGetAttribLocation(mProgram,  "aPosition");
		           maColorHandle = GLES20.glGetAttribLocation(mProgram,  "aColor");
		 muModelViewMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uModelViewMatrix");
		      muViewMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uViewMatrix");
		muProjectionMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uProjectionMatrix");
	}

	private int createProgram(String vertexSource, String fragmentSource) {
		int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
		if (vertexShader == -1) {
			return -1;
		}
		if (vertexShader == -2) {
			return -2;
		}

		int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
		if (pixelShader == 0) {
			return -2;
		}

		int program = GLES20.glCreateProgram();
		if (program != 0) {
			GLES20.glAttachShader(program, vertexShader);
			GLES20.glAttachShader(program, pixelShader);
			GLES20.glLinkProgram(program);
			int[] linkStatus = new int[1];
			GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
			if (linkStatus[0] != GLES20.GL_TRUE) {
				GLES20.glDeleteProgram(program);
				program = -3;
			}
		}
		return program;
	}

	private int loadShader(int shaderType, String source) {
		int shader = GLES20.glCreateShader(shaderType);
		if (shader != 0) {
			GLES20.glShaderSource(shader, source);
			GLES20.glCompileShader(shader);
			int[] compiled = new int[1];
			GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
			if (compiled[0] == 0) {
				GLES20.glDeleteShader(shader);
				shader = 0;
			}
		}
		return shader;
	}

	public void drawPoint(Point points, Camera camera) {
		GLES20.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
		GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
//		GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE);
//		GLES20.glBlendFunc(GLES20.GL_ZERO, GLES20.GL_SRC_COLOR);
//		GLES20.glBlendFunc(GLES20.GL_ZERO, GLES20.GL_ONE_MINUS_SRC_COLOR);
//		GLES20.glBlendFunc(GLES20.GL_ONE_MINUS_DST_COLOR, GLES20.GL_ONE);
		GLES20.glEnable(GLES20.GL_BLEND);
		GLES20.glDisable(GLES20.GL_DEPTH_TEST);
		
		GLES20.glUseProgram(mProgram);
	
		Matrix.setLookAtM(mViewMatrix,0,
				camera.eye[0],    camera.eye[1],    camera.eye[2],
				camera.target[0], camera.target[1], camera.target[2],
				camera.up[0],     camera.up[1],     camera.up[2]);
	
		GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 4 * 3, points.getVertexBuffer());
		GLES20.glEnableVertexAttribArray(maPositionHandle);

		GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4 * 4, points.getColorBuffer());
		GLES20.glEnableVertexAttribArray(maColorHandle);

		mModelViewMatrix = points.getMatrix();
		GLES20.glUniformMatrix4fv(muModelViewMatrixHandle,  1, false, mModelViewMatrix,    0);
		GLES20.glUniformMatrix4fv(muViewMatrixHandle,       1, false, mViewMatrix,    0);
		GLES20.glUniformMatrix4fv(muProjectionMatrixHandle, 1, false, mProjMatrix, 0);
		
		GLES20.glDrawArrays(GLES20.GL_POINTS, 0, Point.MAX_NUMBER);
	
	//			GLES20.glDrawElements(GLES20.GL_POINTS, shape[i].getIndexLength(), GL10.GL_UNSIGNED_SHORT, shape[i].getIndexBuffer());
	}

	public void draw(Shape[] shape, Camera camera) {
		if (mProgram == -1) {
			GLES20.glClearColor(1.0f, 0.3f, 0.3f, 1.0f);
		}else		if (mProgram == -2) {
			GLES20.glClearColor(0.3f, 1.0f, 0.3f, 1.0f);
		}else		if (mProgram == -3) {
			GLES20.glClearColor(0.3f, 0.3f, 1.0f, 1.0f);
		}else
		{
			GLES20.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
		}
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
		GLES20.glEnable(GLES20.GL_DEPTH_TEST);
		GLES20.glDisable(GLES20.GL_BLEND);

		GLES20.glUseProgram(mProgram);

		Matrix.setLookAtM(mViewMatrix,0,
				camera.eye[0],    camera.eye[1],    camera.eye[2],
				camera.target[0], camera.target[1], camera.target[2],
				camera.up[0],     camera.up[1],     camera.up[2]);

		for (int i = 0; i < shape.length; ++i) {
			if (shape[i].is_active()) {
				GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 4 * 3, shape[i].getVertexBuffer());
				GLES20.glEnableVertexAttribArray(maPositionHandle);

				GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4 * 4, shape[i].getColorBuffer());
				GLES20.glEnableVertexAttribArray(maColorHandle);

				mModelViewMatrix = shape[i].getMatrix();
				GLES20.glUniformMatrix4fv(muModelViewMatrixHandle,  1, false, mModelViewMatrix,    0);
				GLES20.glUniformMatrix4fv(muViewMatrixHandle,       1, false, mViewMatrix,    0);
				GLES20.glUniformMatrix4fv(muProjectionMatrixHandle, 1, false, mProjMatrix, 0);

				GLES20.glDrawElements(GL10.GL_TRIANGLES, shape[i].getIndexLength(), GL10.GL_UNSIGNED_SHORT, shape[i].getIndexBuffer());
			}
		}
	}
}
